package helper.scxml.scxml2.t0.case2_traffic.zone.ts

import helper.base.BaseTypeHelper.toIntRange
import helper.base.LHMHelper.A2LHMExpand.add
import helper.base.debug.DebugHelper.DebuggerList.Companion.makeDebuggerList
import helper.base.debug.DebugRes.d_getCalString
import helper.base.debug.DebugRes.d_t_pT1Calculate_path
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.aStart
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.aTrainWait
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.bike
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.getSimpleT1EnvStrategy
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.train
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.trainWaitBack
import helper.scxml.scxml2.t0.case2_traffic.zone.TrafficEnvHelper.StrategyObj.trainWaitTrain
import helper.scxml.scxml2.t0.case2_traffic.zone.ts.T0Helper.TaskUnit.Companion.getTaskUnit
import helper.scxml.strategy.TotalStrategyHelper.KREWTuple.Companion.makeKREWTuple
import helper.scxml.strategy.TotalStrategyHelper.SNode.Companion.makeSNode
import helper.scxml.strategy.sNodeUnit.T2SNodeUnitHelper.ERT2SNodeUnit.Companion.makeL0ERT2SNodeUnit
import helper.scxml.strategy.sNodeUnit.T2SNodeUnitHelper.SubT2SNodeUnit.Companion.makeSubT2SNodeUnit
import helper.scxml.strategy.sNodeUnit.T2SNodeUnitHelper.T2SNodeUnit
import org.junit.Test

internal class T3_trainTwo_byRetry_simple {
    fun getT3T2SNodeUnit(): T2SNodeUnit {
        return makeL0ERT2SNodeUnit(
            env = getSimpleT1EnvStrategy(),
            ren = makeSubT2SNodeUnit().apply {
                relationLHM.add(
                    null,
                    aStart,
                    makeSNode().also { aSNode ->
                        funLHM.add(aSNode) {
                            val enterS0Time = it.byNameFindC("r").getPointD()
                            if (enterS0Time <= 1) {
                                "r<=1"
                            } else {
                                "r>1"
                            }
                        }
                        arrayOf(
                            makeKREWTuple("r<=1", 1.toIntRange(), train, 1),
                            makeKREWTuple("r>1", 1.toIntRange(), bike, 1),
                        ).forEach {
                            addSNode(aSNode, it)
                        }
                    },
                )
                relationLHM.add(
                    null,
                    aTrainWait,
                    makeSNode().also { aSNode ->
                        funLHM.add(aSNode) {
                            val enterS0Time = it.byNameFindC("r").getPointD()
                            if (enterS0Time <= 1) {
                                "r<=1"
                            } else {
                                "r>1"
                            }
                        }
                        arrayOf(
                            makeKREWTuple("r<=1", 1.toIntRange(), trainWaitTrain, 1),
                            makeKREWTuple("r>1", 1.toIntRange(), trainWaitBack, 1),
                        ).forEach {
                            addSNode(aSNode, it)
                        }
                    },
                )
            },
        )
    }

    private val taskUnit = getTaskUnit(getT3T2SNodeUnit())

    @Test
    fun t1() {
        taskUnit.repeatRandomRun(
            1000000,
        )
    }
    //repeatTimes = 1000000
    //average t = 41.628901

    @Test
    fun t3() {
        taskUnit.t1Cal(
            makeDebuggerList(
                d_t_pT1Calculate_path,
                d_getCalString,
            )
        )
    }
    //result={t=41.632231404958674, r=0.09917355371900827}

    @Test
    fun t119() {
        val timeIfBad = 10000
        val s1s11 = 1 / 11.0
        val s10s11 = 10 / 11.0

        val tT = 1 + 5
        val btB = 1 + 1
        val T = 35
        val B = 43.5
        val btBB = btB + B

        val tTT = tT + T
        val tTbtBB = tT + btBB

        val tTtTT = tT + tTT
        val tTtTbtBB = tT + tTbtBB

        val tTtTtTT = tT + tTtTT
        val tTtTtTbtBB = tT + tTtTbtBB

        println("tT=${tT}")
        println("btB=${btB}")
        println("T=${T}")
        println("B=${B}")
        println("tTT=${tTT}")
        println("btBB=${btBB}")
        println("tTtTT=${tTtTT}")
        println("tTbtBB=${tTbtBB}")
        println("tTtTbtBB=${tTtTbtBB}")
        println("tTtTtTT=${tTtTtTT}")
        println("tTtTtTbtBB=${tTtTtTbtBB}")

        (100..timeIfBad).forEach { it ->
            val train1 = (tTT) * s10s11 + tTbtBB * s1s11
            val train2 = (tTT) * s10s11 + (tTtTT * s10s11 + tTtTbtBB * s1s11) * s1s11
            val train3 = (tTT) * s10s11 + (tTtTT * s10s11 + (tTtTtTT * s10s11 + it * s1s11) * s1s11) * s1s11
            println("it=${it},train1=${train1},train2=${train2},train3=${train3}")
        }
    }
    //train1=41.95454545454545,train2=41.63223140495868
}